package cn.zd.thumbbackend.service.impl;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.zd.thumbbackend.constant.RedisLuaScriptConstant;
import cn.zd.thumbbackend.exception.ErrorCode;
import cn.zd.thumbbackend.exception.ThrowUtils;
import cn.zd.thumbbackend.mapper.ThumbMapper;
import cn.zd.thumbbackend.model.dto.thumb.DoThumbRequest;
import cn.zd.thumbbackend.model.entity.Blog;
import cn.zd.thumbbackend.model.entity.Thumb;
import cn.zd.thumbbackend.model.entity.User;
import cn.zd.thumbbackend.model.enums.LuaStatusEnum;
import cn.zd.thumbbackend.service.BlogService;
import cn.zd.thumbbackend.service.ThumbService;
import cn.zd.thumbbackend.service.UserService;
import cn.zd.thumbbackend.util.RedisKeyUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.support.TransactionTemplate;

import java.util.Arrays;

/**
 * @author zheng
 * @description 针对表【thumb】的数据库操作Service实现
 * @createDate 2025-05-20 14:44:44
 */
@Service("thumbServiceRedis")
@Slf4j
@RequiredArgsConstructor
public class ThumbServiceRedisImpl extends ServiceImpl<ThumbMapper, Thumb>
        implements ThumbService {
    
    private final UserService userService;
    
    private final RedisTemplate<String, Object> redisTemplate;
    
    /**
     * 点赞
     *
     * @param doThumbRequest doThumbRequest
     * @param request        request
     * @return {@link Boolean }
     */
    @Override
    public Boolean doThumb(DoThumbRequest doThumbRequest, HttpServletRequest request) {
        ThrowUtils.throwIf((doThumbRequest == null || doThumbRequest.getBlogId() == null), ErrorCode.PARAMS_ERROR);
        User loginUser = userService.getLoginUser(request);
        Long blogId = doThumbRequest.getBlogId();
        
        String timeSlice = getTimeSlice();
        // Redis Key
        String tempThumbKey = RedisKeyUtil.getTempThumbKey(timeSlice);
        String userThumbKey = RedisKeyUtil.getUserThumbKey(loginUser.getId());
        
        // 执行 Lua 脚本
        long result = redisTemplate.execute(
                RedisLuaScriptConstant.THUMB_SCRIPT,
                Arrays.asList(tempThumbKey, userThumbKey),
                loginUser.getId(),
                blogId
        );
        
        ThrowUtils.throwIf(LuaStatusEnum.FAIL.getValue() == result, ErrorCode.HAS_THUMB);
        
        // 更新成功才执行
        return LuaStatusEnum.SUCCESS.getValue() == result;
    }
    
    /**
     * 取消点赞
     *
     * @param doThumbRequest doThumbRequest
     * @param request        request
     * @return {@link Boolean }
     */
    @Override
    public Boolean undoThumb(DoThumbRequest doThumbRequest, HttpServletRequest request) {
        ThrowUtils.throwIf((doThumbRequest == null || doThumbRequest.getBlogId() == null), ErrorCode.PARAMS_ERROR);
        User loginUser = userService.getLoginUser(request);
        
        Long blogId = doThumbRequest.getBlogId();
        // 计算时间片
        String timeSlice = getTimeSlice();
        // Redis Key
        String tempThumbKey = RedisKeyUtil.getTempThumbKey(timeSlice);
        String userThumbKey = RedisKeyUtil.getUserThumbKey(loginUser.getId());
        
        long result = redisTemplate.execute(
                RedisLuaScriptConstant.UNTHUMB_SCRIPT,
                Arrays.asList(tempThumbKey, userThumbKey),
                loginUser.getId(),
                blogId
        );
        
        // 根据返回值处理结果
        ThrowUtils.throwIf(LuaStatusEnum.FAIL.getValue() == result, ErrorCode.NO_HAS_THUMB);
        return LuaStatusEnum.SUCCESS.getValue() == result;
    }
    
    /**
     * 是否点赞
     *
     * @param blogId blogId
     * @param userId userId
     * @return {@link Boolean }
     */
    @Override
    public Boolean hasThumb(Long blogId, Long userId) {
        return redisTemplate.opsForHash().hasKey(RedisKeyUtil.getUserThumbKey(userId), blogId.toString());
    }
    
    private String getTimeSlice() {
        DateTime nowDate = DateUtil.date();
        // 获取当前时间前最近的整数秒，比如当前 15:53:23，获取到 15:53:20
        return DateUtil.format(nowDate, "HH:mm:") + (DateUtil.second(nowDate) / 10) * 10;
    }
    
    
}
